#include "PlatformProperty.h"

MAPPING_VALUE(SeatHeigthMode, sdb::SwtVertSts1, sdb::SwtVertSts1::Idle)
MAPPING_ITEM(SeatHeigthMode::SEAT_HEIGHT_OFF, sdb::SwtVertSts1::Idle)
MAPPING_ITEM(SeatHeigthMode::SEAT_HEIGHT_UP, sdb::SwtVertSts1::Up)
MAPPING_ITEM(SeatHeigthMode::SEAT_HEIGHT_DOWN, sdb::SwtVertSts1::Dwn)
MAPPING_END
MAPPING_VALUE(sdb::SwtVertSts1, SeatHeigthMode, SeatHeigthMode::SEAT_HEIGHT_OFF)
MAPPING_ITEM(sdb::SwtVertSts1::Idle, SeatHeigthMode::SEAT_HEIGHT_OFF)
MAPPING_ITEM(sdb::SwtVertSts1::Up, SeatHeigthMode::SEAT_HEIGHT_UP)
MAPPING_ITEM(sdb::SwtVertSts1::Dwn, SeatHeigthMode::SEAT_HEIGHT_DOWN)
MAPPING_END
sdb::Boolean m_LastDrvrSeatExtAdjAllowdHightMove = sdb::Boolean::FALSE;
std::map<int32_t, int32_t> m_SeatAdjustmentVFCHightMove;

void SeatAdjustmentChangeVFC_IdleToOtherHightMove(SignalTX iSignal, int32_t iValue) {
    int32_t ikey = static_cast<int32_t>(iSignal);
    std::map<int32_t, int32_t>::iterator it = m_SeatAdjustmentVFCHightMove.find(ikey);
    int32_t idle = static_cast<int32_t>(sdb::SwtVertSts1::Idle);
    if (it == m_SeatAdjustmentVFCHightMove.end()) {
        m_SeatAdjustmentVFCHightMove[ikey] = idle;
    }
    VHALOG.d("SeatAdjustmentChangeVFC_IdleToOtherHightMove-iValue=%d,last=%d,Signal=%d,key=%d", iValue, m_SeatAdjustmentVFCHightMove[ikey],
             iSignal, ikey);
    if (idle == m_SeatAdjustmentVFCHightMove[ikey] && idle != iValue && !SIGNAL.usgModeIs(sdb::UsgModSts1::UsgModAbdnd)) {
        SIGNAL.setCB_VFC_SeatComfortFunctions(sdb::OnOff1::On);
    }
    m_SeatAdjustmentVFCHightMove[ikey] = iValue;
}

// 3.2.7 [SW_FC_004_044]第一排座椅高度调节 1stRowSeatHeightAdjustment
SYSTEM_READ_WRITE_PROPERTY(SEAT_HEIGHT_MOVE, SeatHeigthMode) {
    builder.area(VehicleAreaSeat::ROW_1_LEFT)
        .initValue([]() {
            return SeatHeigthMode::SEAT_HEIGHT_OFF;
        })
        .withStatusBySignals(
            []([[maybe_unused]] const PropertyStatus& lastStatus) {
                sdb::Boolean drvrSeatExtAdjAllowd = SIGNAL.getDrvrSeatExtAdjAllowd();
                sdb::Timeout drvrSeatExtAdjAllowdTimeout = SIGNAL.getDrvrSeatExtAdjAllowdTimeout();
                sdb::GearLvrIndcn2 gearLvrIndcn = SIGNAL.getGearLvrIndcn();
                auto drvrSeatBtnPsd = SIGNAL.getDrvrSeatBtnPsd();

                VHALOG.d(
                    "SEAT_HEIGHT_MOVE status drvr carmod[%d], usgmod[%d], cc472[%d], cc1173[%d], drvrSeatExtAdjAllowd[%d], "
                    "drvrSeatExtAdjAllowdTimeout[%d], gearLvrIndcn[%d] ,drvrSeatBtnPsd[%d]",
                    SIGNAL.getVehModMngtGlbSafe1CarModSts1(),
                    SIGNAL.getVehModMngtGlbSafe1UsgModSts(), SIGNAL.getcarconfig472(),
                    SIGNAL.getcarconfig1173(), drvrSeatExtAdjAllowd, drvrSeatExtAdjAllowdTimeout,
                    gearLvrIndcn, static_cast<int32_t>(drvrSeatBtnPsd));

                if (gearLvrIndcn != sdb::GearLvrIndcn2::ParkIndcn) {
                    drvrSeatExtAdjAllowd = sdb::Boolean::FALSE;
                } else if (drvrSeatExtAdjAllowdTimeout == sdb::Timeout::Timeout) {
                    if (SIGNAL.usgModeIs(sdb::UsgModSts1::UsgModActv,
                                         sdb::UsgModSts1::UsgModDrvg)) {
                        drvrSeatExtAdjAllowd = sdb::Boolean::FALSE;
                    } else {
                        drvrSeatExtAdjAllowd = m_LastDrvrSeatExtAdjAllowdHightMove;
                    }
                }
                m_LastDrvrSeatExtAdjAllowdHightMove = drvrSeatExtAdjAllowd;

                if (SIGNAL.carConfigIs(SignalRX::carconfig472,
                                       sdb::CarConfig472::_02,
                                       sdb::CarConfig472::_03) &&
                    SIGNAL.carConfigIs(SignalRX::carconfig1173,
                                       sdb::CarConfig1173::_02)) {
                    if (SIGNAL.carModeIs(sdb::CarModSts1::CarModCrash,
                                         sdb::CarModSts1::CarModDyno,
                                         sdb::CarModSts1::CarModNorm) &&
                        SIGNAL.usgModeIs(sdb::UsgModSts1::UsgModInActv,
                                         sdb::UsgModSts1::UsgModCnvinc,
                                         sdb::UsgModSts1::UsgModActv,
                                         sdb::UsgModSts1::UsgModDrvg) &&
                        drvrSeatExtAdjAllowd == sdb::Boolean::TRUE &&
                        drvrSeatBtnPsd == sdb::Boolean::FALSE) {
                        VHALOG.d("SEAT_HEIGHT_MOVE drvr Active");
                        return PropertyStatus::Active;
                    }
                    VHALOG.d("SEAT_HEIGHT_MOVE drvr NotActive");
                    return PropertyStatus::NotActive;
                }
                VHALOG.d("SEAT_HEIGHT_MOVE drvr NotAvailable");
                return PropertyStatus::NotAvailable;
            },
            SignalRX::carconfig472,
            SignalRX::carconfig1173,
            SignalRX::DrvrSeatExtAdjAllowd,
            SignalRX::DrvrSeatExtAdjAllowdTimeout,
            SignalRX::VehModMngtGlbSafe1UsgModSts,
            SignalRX::VehModMngtGlbSafe1CarModSts1,
            SignalRX::GearLvrIndcn,
            SignalRX::DrvrSeatBtnPsd)
        .withValueBySignals(
            []([[maybe_unused]] const SeatHeigthMode last) {
                auto heiSts = SIGNAL.getDrvrSeatSwtStsDrvrSeatSwtHeiSts();
                auto heightPerc = static_cast<int32_t>(SIGNAL.getDrvrSeatPosPercSeatPosHeiPerc());
                bool qfIsReaday = SIGNAL.getDrvrSeatPosPercSeatPosHeiQF() == sdb::Qf1::DataCalcdWithDevDefd;
                auto drvrSeatBtnPsd = SIGNAL.getDrvrSeatBtnPsd();
                VHALOG.d("SEAT_HEIGHT_MOVE  drvr last:%d, heiSts:%d heightPerc:%d drvrSeatBtnPsd:%d", toInt(last),
                         static_cast<int32_t>(heiSts), heightPerc, static_cast<int32_t>(drvrSeatBtnPsd));

                if (drvrSeatBtnPsd == sdb::Boolean::TRUE ||                                   // 硬按键按下时需要按idle处理
                    (qfIsReaday && (heightPerc == 100 && heiSts == sdb::SwtVertSts1::Up)) ||  // 无法再向上
                    (qfIsReaday && (heightPerc == 0 && heiSts == sdb::SwtVertSts1::Dwn))) {   // 无法再向下
                    VHALOG.d("SEAT_HEIGHT_MOVE drvr trigger to idle");
                    SeatAdjustmentChangeVFC_IdleToOtherHightMove(SignalTX::SeatHeiAdjmtRowFirstDrvr,
                                                                 static_cast<int32_t>(sdb::SwtVertSts1::Idle));
                    SIGNAL.setSeatHeiAdjmtRowFirstDrvr(sdb::SwtVertSts1::Idle);
                    return SeatHeigthMode::SEAT_HEIGHT_OFF;
                }
                return mappingValue(heiSts, SeatHeigthMode::SEAT_HEIGHT_OFF);
            },
            SignalRX::DrvrSeatPosPercSeatPosHeiPerc,
            SignalRX::DrvrSeatPosPercSeatPosHeiQF,
            SignalRX::DrvrSeatBtnPsd,
            SignalRX::DrvrSeatSwtStsDrvrSeatSwtHeiSts)
        .onSetProperty(
            [](const SeatHeigthMode value) {
                if (value != SeatHeigthMode::SEAT_HEIGHT_OFF && value != SeatHeigthMode::SEAT_HEIGHT_DOWN && value != SeatHeigthMode::SEAT_HEIGHT_UP) {
                    VHALOG.e("SEAT_HEIGHT_MOVE drvr: param invalid");
                    return;
                }
                bool qfIsReaday = SIGNAL.getDrvrSeatPosPercSeatPosHeiQF() == sdb::Qf1::DataCalcdWithDevDefd;
                auto heightPerc = static_cast<int32_t>(SIGNAL.getDrvrSeatPosPercSeatPosHeiPerc());
                if (qfIsReaday && heightPerc == 100 && value == SeatHeigthMode::SEAT_HEIGHT_UP) {
                    SIGNAL.setSeatHeiAdjmtRowFirstDrvr(sdb::SwtVertSts1::Idle);
                    VHALOG.e("SEAT_HEIGHT_MOVE drvr: the percent is 100 , can not up");
                    return;
                } else if (qfIsReaday && heightPerc == 0 && value == SeatHeigthMode::SEAT_HEIGHT_DOWN) {
                    VHALOG.e("SEAT_HEIGHT_MOVE drvr: the percent is 0 , can not down");
                    SIGNAL.setSeatHeiAdjmtRowFirstDrvr(sdb::SwtVertSts1::Idle);
                    return;
                }
                VHALOG.d("SEAT_HEIGHT_MOVE drvr: setValue[%d]", value);

                sdb::SwtVertSts1 TempSeatHeiAdjmtRowFirstDrvr = mappingValue(value, sdb::SwtVertSts1::Idle);
                SeatAdjustmentChangeVFC_IdleToOtherHightMove(SignalTX::SeatHeiAdjmtRowFirstDrvr,
                                                             static_cast<int32_t>(TempSeatHeiAdjmtRowFirstDrvr));
                SIGNAL.setSeatHeiAdjmtRowFirstDrvr(TempSeatHeiAdjmtRowFirstDrvr);
            })
        .area(VehicleAreaSeat::ROW_1_RIGHT)
        .initValue([]() {
            return SeatHeigthMode::SEAT_HEIGHT_OFF;
        })
        .withStatusBySignals(
            []([[maybe_unused]] const PropertyStatus& lastStatus) {
                auto passSeatBtnPsd = SIGNAL.getPassSeatBtnPsd();
                VHALOG.d("SEAT_HEIGHT_MOVE pass status Change carmod[%d], usgmod[%d], cc472[%d], cc1174[%d],passSeatBtnPsd[%d]",
                         SIGNAL.getVehModMngtGlbSafe1CarModSts1(), SIGNAL.getVehModMngtGlbSafe1UsgModSts(),
                         SIGNAL.getcarconfig472(), SIGNAL.getcarconfig1174(), static_cast<int32_t>(passSeatBtnPsd));
                if (SIGNAL.carConfigIs(SignalRX::carconfig472,
                                       sdb::CarConfig472::_02) &&
                    SIGNAL.carConfigIs(SignalRX::carconfig1174,
                                       sdb::CarConfig1174::_02)) {
                    if (SIGNAL.carModeIs(sdb::CarModSts1::CarModCrash,
                                         sdb::CarModSts1::CarModDyno,
                                         sdb::CarModSts1::CarModNorm) &&
                        SIGNAL.usgModeIs(sdb::UsgModSts1::UsgModInActv,
                                         sdb::UsgModSts1::UsgModCnvinc,
                                         sdb::UsgModSts1::UsgModActv,
                                         sdb::UsgModSts1::UsgModDrvg) &&
                        passSeatBtnPsd == sdb::Boolean::FALSE) {
                        VHALOG.d("SEAT_HEIGHT_MOVE pass Active");
                        return PropertyStatus::Active;
                    }
                    VHALOG.d("SEAT_HEIGHT_MOVE pass NotActive");
                    return PropertyStatus::NotActive;
                }
                VHALOG.d("SEAT_HEIGHT_MOVE pass NotAvailable");
                return PropertyStatus::NotAvailable;
            },
            SignalRX::carconfig472,
            SignalRX::carconfig1174,
            SignalRX::VehModMngtGlbSafe1UsgModSts,
            SignalRX::VehModMngtGlbSafe1CarModSts1,
            SignalRX::PassSeatBtnPsd)
        .withValueBySignals(
            []([[maybe_unused]] const SeatHeigthMode last) {
                auto heiSts = SIGNAL.getPassSeatSwtSts2PassSeatSwtHeiSts();
                auto heightPerc = static_cast<int32_t>(SIGNAL.getPassSeatPosPercSeatPosHeiPerc());
                bool qfIsReaday = SIGNAL.getPassSeatPosPercSeatPosHeiQF() == sdb::Qf1::DataCalcdWithDevDefd;
                auto passSeatBtnPsd = SIGNAL.getPassSeatBtnPsd();
                VHALOG.d("SEAT_HEIGHT_MOVE  pass last:%d, heiSts:%d heightPerc:%d passSeatBtnPsd:%d",
                         toInt(last), static_cast<int32_t>(heiSts), heightPerc, static_cast<int32_t>(passSeatBtnPsd));

                if (passSeatBtnPsd == sdb::Boolean::TRUE ||                                   // 硬按键按下时需要按idle处理
                    (qfIsReaday && (heightPerc == 100 && heiSts == sdb::SwtVertSts1::Up)) ||  // 无法再向上
                    (qfIsReaday && (heightPerc == 0 && heiSts == sdb::SwtVertSts1::Dwn))) {   // 无法再向下
                    VHALOG.d("SEAT_HEIGHT_MOVE pass trigger to idle");
                    SeatAdjustmentChangeVFC_IdleToOtherHightMove(SignalTX::SeatHeiAdjmtRowFirstPass,
                                                                 static_cast<int32_t>(sdb::SwtVertSts1::Idle));
                    SIGNAL.setSeatHeiAdjmtRowFirstPass(sdb::SwtVertSts1::Idle);
                    return SeatHeigthMode::SEAT_HEIGHT_OFF;
                }
                return mappingValue(heiSts, SeatHeigthMode::SEAT_HEIGHT_OFF);
            },
            SignalRX::PassSeatPosPercSeatPosHeiPerc,
            SignalRX::PassSeatPosPercSeatPosHeiQF,
            SignalRX::PassSeatBtnPsd,
            SignalRX::PassSeatSwtSts2PassSeatSwtHeiSts)
        .onSetProperty(
            [](const SeatHeigthMode value) {
                if (value != SeatHeigthMode::SEAT_HEIGHT_OFF && value != SeatHeigthMode::SEAT_HEIGHT_DOWN && value != SeatHeigthMode::SEAT_HEIGHT_UP) {
                    VHALOG.e("SEAT_HEIGHT_MOVE pass: param invalid");
                    return;
                }
                bool qfIsReaday = SIGNAL.getPassSeatPosPercSeatPosHeiQF() == sdb::Qf1::DataCalcdWithDevDefd;
                auto heightPerc = static_cast<int32_t>(SIGNAL.getPassSeatPosPercSeatPosHeiPerc());
                if (qfIsReaday && heightPerc == 100 && value == SeatHeigthMode::SEAT_HEIGHT_UP) {
                    VHALOG.e("SEAT_HEIGHT_MOVE pass: the percent is 100 , can not up");
                    SIGNAL.setSeatHeiAdjmtRowFirstPass(sdb::SwtVertSts1::Idle);
                    return;
                } else if (qfIsReaday && heightPerc == 0 && value == SeatHeigthMode::SEAT_HEIGHT_DOWN) {
                    VHALOG.e("SEAT_HEIGHT_MOVE pass: the percent is 0 , can not down");
                    SIGNAL.setSeatHeiAdjmtRowFirstPass(sdb::SwtVertSts1::Idle);
                    return;
                }
                VHALOG.d("SEAT_HEIGHT_MOVE pass: setValue[%d]", value);

                sdb::SwtVertSts1 TempSeatHeiAdjmtRowFirstPass = mappingValue(value, sdb::SwtVertSts1::Idle);
                SeatAdjustmentChangeVFC_IdleToOtherHightMove(SignalTX::SeatHeiAdjmtRowFirstPass,
                                                             static_cast<int32_t>(TempSeatHeiAdjmtRowFirstPass));
                SIGNAL.setSeatHeiAdjmtRowFirstPass(TempSeatHeiAdjmtRowFirstPass);
            });
}
